package com.hst.capacity.application.biz.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.hst.capacity.application.biz.SpecialOrderBiz;
import com.hst.capacity.domain.common.constants.Constants;
import com.hst.capacity.domain.exception.BusinessException;
import com.hst.capacity.domain.model.entity.account.SpecialDriverAccountDetailEntity;
import com.hst.capacity.domain.model.entity.order.specialcar.SpCarOrderCancelHistoryEntity;
import com.hst.capacity.domain.model.entity.order.specialcar.SpCarOrderDispatchEntity;
import com.hst.capacity.domain.model.entity.order.specialcar.SpCarOrderEntity;
import com.hst.capacity.domain.model.entity.order.specialcar.SpCarOrderSettlementEntity;
import com.hst.capacity.domain.model.entity.vehicle.VehicleEntity;
import com.hst.capacity.domain.model.request.dispatch.DispatchDriverParam;
import com.hst.capacity.domain.model.request.specialcar.SpCarSettlementViewListParam;
import com.hst.capacity.domain.model.request.specialcar.SpListParam;
import com.hst.capacity.domain.model.request.specialcar.SpOrderDestroyParam;
import com.hst.capacity.domain.model.response.PagingResultVO;
import com.hst.capacity.domain.model.response.order.OrderBillInfoVO;
import com.hst.capacity.domain.model.response.specialcar.SpDetailVO;
import com.hst.capacity.domain.model.response.specialcar.SpListNewVO;
import com.hst.capacity.domain.model.response.specialcar.SpSearchVO;
import com.hst.capacity.domain.model.response.specialcar.SpSettlementViewVO;
import com.hst.capacity.domain.service.SpecialService;
import com.hst.capacity.infra.convertor.ExpressConvertor;
import com.hst.capacity.infra.convertor.SpecialConvertor;
import com.hst.capacity.infra.persistence.jpa.account.SpecialDriverAccountDetailRepository;
import com.hst.capacity.infra.persistence.jpa.order.specialcar.*;
import com.hst.capacity.infra.persistence.jpa.vehicle.VehicleRepository;
import com.hst.capacity.infra.persistence.mybatis.SpecialOrderMapper;
import com.hst.capacity.infra.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;

@Service
public class SpecialOrderBizImpl implements SpecialOrderBiz {

    @Autowired
    private SpCarOrderRepository orderRepository;

    @Autowired
    private SpOrderSettlementRepository orderSettlementRepository;

    @Autowired
    private SpecialDriverAccountDetailRepository accountDetailRepository;
    @Autowired
    private SpecialService specialService;
    @Autowired
    private SpecialOrderMapper orderMapper;
    @Autowired
    private SpCarOrderRepository spOrderRepository;
    @Autowired
    private SpOrderDestroyRepository destroyRepository;
    @Autowired
    private SpOrderDispatchRepository dispatchRepository;
    @Autowired
    private SpCarOrderCancelHistoryRepository orderCancelHistoryRepository;
    @Autowired
    private VehicleRepository vehicleRepository;


    /**
     * 订单检索查询
     * @param param
     * @return
     */
    @Override
    public PagingResultVO<SpSearchVO> spOrderSearch(SpListParam param) {
        return new PagingResultVO<>(orderMapper.searchWithConditionsAndPagingTotal(param), orderMapper.searchWithConditionsAndPaging(param));
    }

    /**
     * 获取今日创建的快车订单
     * @param param
     * @return
     */
    @Override
    public PagingResultVO<SpListNewVO> getNewOrderListByRegionCode(SpListParam param) {
        SpListParam convert = Convert.convert(SpListParam.class, param);
        convert.setCreatTimeF(DateUtil.getStartTimeOfDay());
        convert.setCreatTimeE(DateUtil.getEndTimeOfDay());
        convert.setRegionCodes(param.getRegionCodes());
        return SpecialConvertor.INSTANCE.convertNew(specialService.searchWithConditionsAndPaging(convert));
    }

    /**
     * 快车司机改派
     * @param param
     * @return
     */
    @Override
    public Boolean reDispatchDriver(DispatchDriverParam param) {
        boolean result = orderRepository.updateDriver(param.getIdDriver(), param.getIdOrder()) == 1;
        if (result){
            dispatchRepository.save(new SpCarOrderDispatchEntity(param));
        }

        return result;
    }

    /**
     * 订单详情
     * @param idOrder
     * @return
     */
    @Override
    public SpDetailVO spOrderDetail(String idOrder) {

        List<SpDetailVO.StatusHistory> statusHistories = orderMapper.spOrderDetailHistory(idOrder);
        List<SpDetailVO.StatusHistory> statusHistoriesR = new ArrayList<>();
        SpDetailVO.Base base = orderMapper.spOrderDetailBase(idOrder);
        if (base==null)throw new BusinessException(5002,"订单号不存在请检查");
        ArrayList<String> child;
        SpCarOrderEntity orderEntity = spOrderRepository.findById(idOrder).get();
        SpCarOrderCancelHistoryEntity och = orderCancelHistoryRepository.findById(idOrder).orElse(null);

        for (SpDetailVO.StatusHistory v:statusHistories) {
            child = new ArrayList<>();
            switch (v.getStatus()){
                case 0://乘客发单
                    v.setTitle("乘客发单");
                    child.add(StrUtil.join(":","发单时间",v.getCreateTime()));
                    child.add(StrUtil.join(":","预估里程/时长",StrUtil.builder().append(orderEntity.getReferenceDistance()).append("公里/").append(orderEntity.getEstimatedTime()).append("分钟")));
                    child.add(StrUtil.join(":","预估价格","￥"+orderEntity.getEstimatedMoney()));
                    statusHistoriesR.add(v);
                    break;
//                case 1://平台派单
//                    v.setTitle("平台派单");
//                    child.add(StrUtil.join(":","车牌号",StrUtil.builder().append(orderEntity.getPlateNumber())));
//                    child.add(StrUtil.join(":","车辆",StrUtil.builder().append(orderEntity.getModel())));
//                    child.add(StrUtil.join(":","预估接驾",StrUtil.builder().append("待定")));
//                    statusHistoriesR.add(v);
//                    break;
                case 2://司机接单
                    if (orderEntity.getIdDriver()!=null){
                        v.setTitle("司机接单");
                        VehicleEntity dv = vehicleRepository.findByIdDriver(orderEntity.getIdDriver());
                        child.add(StrUtil.join(":","接单时间",v.getCreateTime()));
                        child.add(StrUtil.join(":","车牌号",StrUtil.builder().append(dv.getPlateNumber())));
                        //child.add(StrUtil.join(":","车辆",StrUtil.builder().append(orderEntity.getModel())));
                        child.add(StrUtil.join(":","预估接驾里程/时长",StrUtil.builder().append("待定")));
                        statusHistoriesR.add(v);
                    }

                    break;
                case 4://司机到达上车点
                    v.setTitle("司机到达上车点");
                    child.add(StrUtil.join(":","到达上车地点时间",v.getCreateTime()));
                    child.add(StrUtil.join(":","真实接驾里程/时长",StrUtil.builder().append("待定")));
                    statusHistoriesR.add(v);
                    break;
                case 5://乘客上车
                    v.setTitle("乘客上车");
                    child.add(StrUtil.join(":","上车时间",v.getCreateTime()));
                    statusHistoriesR.add(v);
                    break;
                case 6://到达目的地
                    v.setTitle("到达目的地");
                    child.add(StrUtil.join(":","到达时间",v.getCreateTime()));
                    child.add(StrUtil.join(":","实际里程",orderEntity.getOrderDistance()));
                    statusHistoriesR.add(v);
                    break;
                case 7://未支付
                    v.setTitle("订单待支付");
                    child.add(StrUtil.join(":","支付状态",StrUtil.builder().append("未支付")));
                    child.add(StrUtil.join(":","支付时间",v.getCreateTime()));
                    child.add(StrUtil.join(":","乘客应付",orderEntity.getPayMoney()));
                    child.add(StrUtil.join(":","司机应收",orderEntity.getOrderMoney()));
                    statusHistoriesR.add(v);
                    break;
                case 8://已支付
                    v.setTitle("订单支付");
                    child.add(StrUtil.join(":","支付状态",StrUtil.builder().append("已支付")));
                    child.add(StrUtil.join(":","支付时间",v.getCreateTime()));
                    child.add(StrUtil.join(":","乘客应付",orderEntity.getPayMoney()));
                    child.add(StrUtil.join(":","司机应收",orderEntity.getOrderMoney()));
                    statusHistoriesR.add(v);
                    break;
                case 11://乘客下单后取消订单 用户取消、取消原因、操作时间
                    v.setTitle("已取消");
                    child.add("用户取消");
                    if(och!=null){
                        child.add(StrUtil.join(":","取消原因",och.getReason()));
                        child.add(StrUtil.join(":","操作时间",och.getCreateTime()));
                    }
                    statusHistoriesR.add(v);
                    break;
//                case 12://司机已拒绝
//                    v.setTitle("司机已拒绝");
//                    child.add(StrUtil.join(":","真实接驾",StrUtil.builder().append("待定")));
//                    statusHistoriesR.add(v);
//                    break;
                case 13://系统已销单
                    v.setTitle("已取消");
                    child.add("系统取消");
                    if(och!=null){
                        child.add(StrUtil.join(":","取消原因",och.getReason()));
                        child.add(StrUtil.join(":","操作时间",och.getCreateTime()));
                    }
                    statusHistoriesR.add(v);
                    break;
                case 14://司机已取消
                    v.setTitle("已取消");
                    child.add("司机取消");
                    if(och!=null){
                        child.add(StrUtil.join(":","取消原因",och.getReason()));
                        child.add(StrUtil.join(":","操作时间",och.getCreateTime()));
                    }
                    statusHistoriesR.add(v);
                    break;
                case 15://客服已取消
                    v.setTitle("已取消");
                    child.add("客服取消");
                    if(och!=null){
                        child.add(StrUtil.join(":","取消原因",och.getReason()));
                        child.add(StrUtil.join(":","操作时间",och.getCreateTime()));
                    }
                    statusHistoriesR.add(v);
                    break;
            }
            v.setChild(child);
        }
        return new SpDetailVO(base, statusHistoriesR,null);
    }

    @Override
    public Boolean spOrderDestroy(SpOrderDestroyParam param) {
        SpCarOrderEntity specialCarOrderEntity;
        try {
            specialCarOrderEntity = spOrderRepository.findById(param.getIdOrder()).get();
            if (specialCarOrderEntity.getStatus()== Constants.OrderStatus.ORDER_STATUS_ADMIN_CANCELED)
                throw new BusinessException(5002,"该订单已被销单,无法重复销单");
        }catch (NoSuchElementException e){
            throw new BusinessException(5002,"订单ID[idOrder]不存在,请检查");
        }
        specialCarOrderEntity.setStatus(Constants.OrderStatus.ORDER_STATUS_ADMIN_CANCELED);
        spOrderRepository.save(specialCarOrderEntity);
        return destroyRepository.save(ExpressConvertor.INSTANCE.convert(param))!=null;
    }

    @Override
    public Boolean spReMemo(String idOrder, String memo) {
        return orderMapper.spReMemo(idOrder,memo);
    }


    /**
     * 订单支付详情
     * @param idOrder
     * @return
     */
    @Override
    public OrderBillInfoVO getOrderBillInfo(String idOrder) {

        SpCarOrderEntity order = orderRepository.findById(idOrder).orElse(null);
        if (order==null)throw new BusinessException(5002,"订单号不存在请检查");

        SpCarOrderSettlementEntity es = orderSettlementRepository.findByIdOrder(idOrder);
        SpecialDriverAccountDetailEntity ed = accountDetailRepository.findByRelateOrderNo(idOrder);

        if (es == null)
            es = new SpCarOrderSettlementEntity();
        if (ed == null)
            ed = new SpecialDriverAccountDetailEntity();

        OrderBillInfoVO.PassengerBill pb = new OrderBillInfoVO.PassengerBill();
        /** 总价 */
        pb.setTotal(es.getOrderTotal());
        /** 基础费 */
        pb.setBasic(es.getOrderMoney());
        /** 时长费 */
        pb.setDuration(0F);
        /** 远途费 */
        pb.setLongDistance(es.getOrderLongDistanceMoney());
        /** 等待费 */
        pb.setWaiting(0F);
        /** 加价费 */
        pb.setPlus(0F);
        OrderBillInfoVO.PassengerPayInfo pp = new OrderBillInfoVO.PassengerPayInfo();
        /** 支付金额 */
        pp.setPayMoney(order.getPayMoney());
        /** 支付时间 */
        if (es.getPayTime()!=null){
            pp.setPayTime(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(es.getPayTime()));
        }
        /** 支付状态 */
        pp.setPayStatus(Constants.Payment_Status.get(order.getPaymentStatus()));
        /** 支付渠道 */
        pp.setPayChannel(Constants.Payment_Type.get(es.getPaymentType()));
        /** 发票状态 */
        pp.setInvoiceStatus("-");
        /** 退款费用 */
        pp.setRefund(0F);
        /** 高速费 */
        pp.setHighSpeed(0F);
        /** 停车费 */
        pp.setParking(0F);
        /** 路桥费 */
        pp.setBridge(es.getOrderRoadMoney());
        /** 限时折扣 */
        pp.setDiscount(0F);
        /** 其他费 */
        pp.setOther(es.getOrderOther());
        /** 节假日服务费 */
        pp.setHoliday(0F);

        OrderBillInfoVO.DriverBill db = new OrderBillInfoVO.DriverBill();
        /** 总价 */
        if (ed != null){
            db.setTotal(ed.getMoney());
        }else{
            db.setTotal(0F);
        }
        /** 基础费 */
        db.setBasic(0F);
        /** 时长费 */
        db.setDuration(0F);
        /** 里程费 */
        db.setMileage(0F);
        /** 高速费 */
        db.setHighSpeed(0F);
        /** 停车费 */
        db.setParking(0F);
        /** 路桥费 */
        db.setBridge(0F);
        /** 远途费 */
        db.setLongDistance(0F);
        /** 其他费 */
        db.setOther(0F);
        /** 免佣补贴金额 */
        db.setAllowance(0F);
        /** 节假日服务费 */
        db.setHoliday(0F);
        /** 信息服务费 */
        db.setInformation(0F);

        return new OrderBillInfoVO(pb, pp,db);
    }

    @Override
    public PagingResultVO<SpSettlementViewVO> spCarOrderBillViewLst(SpCarSettlementViewListParam param) {
        Page<SpSettlementViewVO> page = orderSettlementRepository.findByIdFranchisee(param.getIdFranchisee(), PageRequest.of(param.getPageIndex() - 1, param.getPageSize()));
        return new PagingResultVO<>(page.getTotalElements(),page.getContent());
    }
}
